import uuid
from typing import Optional

from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, Field

from app.agent.toolcall import ToolCallAgent
from app.logger import logger
from app.mcp.client import get_mcp_tools
from app.tool.file.read import ReadFile
from app.tool.tavily_search import tavily_search

agent_api = FastAPI()


class ChatParams(BaseModel):
    user: str = Field(..., description="用户名")
    msg: Optional[str] = Field(None, description="用户消息")
    tool_type: Optional[int] = Field(default=0, description="工具类型: 0=无工具, 1=MCP, 2=Function Calling")
    thread_id: Optional[str] = Field(default=None, description="会话ID，None表示需要开启新对话")


class AgentResponse(BaseModel):
    code: int = status.HTTP_200_OK
    response: Optional[str] = None
    thread_id: Optional[str] = None


def create_thread_id():
    return uuid.uuid4().hex[:8]


# 存储活跃的agent实例
agents: dict[str, ToolCallAgent] = {}


def get_agent(user: str) -> ToolCallAgent:
    """获取或创建用户agent"""
    if user not in agents:
        logger.info(f"Creating new agent for user: {user}")
        agents[user] = ToolCallAgent(name=f"AI Agent of {user}")
    return agents[user]


def set_agent_tools(agent: ToolCallAgent, tool_type: int) -> None:
    """根据工具类型设置agent工具"""
    if tool_type == 1:
        # 异步设置MCP工具
        agent.tools = get_mcp_tools()
    elif tool_type == 2:
        agent.tools = [ReadFile(), tavily_search]


@agent_api.post("/agent/chat", response_model=AgentResponse, description="与 AI Agent 对话")
async def chat_with_agent(params: ChatParams):
    """
   与AI Agent进行对话的主要接口, 支持多种工具类型。

   - **user**: 用户名（必需）
   - **msg**: 用户消息（可选，为空时仅创建新会话）
   - **tool_type**: 工具类型（0: 无工具, 1: MCP, 2: Function Calling）
   - **thread_id**: 会话ID（为空时自动创建）
   """
    # 如果没有提供thread_id，开启新对话
    thread_id = params.thread_id if params.thread_id else create_thread_id()

    if not params.msg:
        logger.info(f"Empty message, returning thread_id: {thread_id}")
        return AgentResponse(thread_id=thread_id)

    try:
        agent = get_agent(params.user)
        agent.thread_id = thread_id
        agent.input_msg_of_this_round = [{"role": "user", "content": params.msg}]
        set_agent_tools(agent, params.tool_type)

        logger.info(f"Running agent for user: {params.user}, thread: {thread_id}")

        res = await agent.run()
        response_content = res[-1]["messages"][-1].content
        return AgentResponse(response=response_content, thread_id=thread_id)
    except Exception as e:
        logger.error(f"Agent execution failed for user {params.user}: {e}", exc_info=True)
        raise HTTPException(status_code=e.status_code, detail=str(e))


@agent_api.delete("/agent/{user}", response_model=AgentResponse, description="删除用户会话")
async def delete_conversation(user: str):
    """删除用户的会话数据"""
    if user in agents:
        del agents[user]
    return AgentResponse(response=f"Conversation of {user} deleted.")


@agent_api.get("/health", description="检查服务是否正常运行")
async def health_check() -> dict:
    """健康检查接口"""
    return {"status": "healthy", "agents_count": len(agents)}


@agent_api.get("/auth", description="获取用户权限")
async def get_auth() -> dict:
    """获取用户权限"""
    return {
        "code": status.HTTP_200_OK,
        "result": {
            "name": "test user",
            "role": "admin"
        }}
